package com.qg.auth.config;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qg.auth.interceptor.LoginInterceptor;
import com.qg.auth.properties.QgAuthProperties;
import com.qg.auth.util.WebBeanFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.text.SimpleDateFormat;
import java.util.List;

/**
 * @Author QG
 * @Date 2023/5/25 16:04
 * @description
 **/
@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties({QgAuthProperties.class})
@ComponentScan("com.qg.auth.handler")
public class QgAuthConfiguration implements WebMvcConfigurer, ApplicationContextAware {
    private static final Logger logger = LoggerFactory.getLogger(QgAuthConfiguration.class);

    @Autowired
    private QgAuthProperties qgAuthProperties;

    private ApplicationContext applicationContext;

    @Value("${system.knife4j.enable:false}")
    private Boolean swagger;

    @Value("${error.path:/error}")
    private String errorPath;

    @Bean
    @ConditionalOnMissingBean(MappingJackson2HttpMessageConverter.class)
    public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        converter.setObjectMapper(mapper);
        return converter;
    }

    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(jackson2HttpMessageConverter());
    }

    @Bean
    public LoginInterceptor loginInterceptor() {
        LoginInterceptor loginInterceptor = new LoginInterceptor();
        return loginInterceptor;
    }

    public boolean enableSwagger() {
        return swagger;
    }

    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration addInterceptor = registry.addInterceptor(loginInterceptor());
        // 前端如果包打过来是static和index.html，无需配置staticPath
        addInterceptor.excludePathPatterns("/static/**");
        addInterceptor.excludePathPatterns("/**/*.html");
        // swagger开启
        if (enableSwagger()) {
            addInterceptor.excludePathPatterns("/swagger-resources/**");
            addInterceptor.excludePathPatterns("/webjars/**");
            addInterceptor.excludePathPatterns("/v2/**");
            addInterceptor.excludePathPatterns("/swagger-ui.html/**");
            addInterceptor.excludePathPatterns("/doc.html/**");
        }
        //注释掉以下这行，是因为拦截器中往全局上下文设置了request和response用于后续使用，登录路径如果在这里放行，后续拦截器无法使用，会出现nullpoint
//        addInterceptor.excludePathPatterns(qgAuthProperties.getLoginUri());
        //不排除此路径，发生错误时请求会被转发到此路径（即 /error）
        addInterceptor.excludePathPatterns(errorPath);
        addInterceptor.addPathPatterns("/**");
    }

    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        if (enableSwagger()) {
            registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
            registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        }
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if(null == this.applicationContext) {
            this.applicationContext = applicationContext;
        }
        WebBeanFactory.setApplicationContext(applicationContext);
    }
}
